﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Windows.ApplicationModel.AppService;
using Windows.Foundation.Collections;
using Windows.Graphics.Display;
using Windows.Foundation;
using System.Threading;
using Logger;
using Windows.System.Display;

namespace Xiaowei.Services
{
    public interface IDisplayReleaseHandler
    {
        /// <summary>
        /// You can just call this function on the thread which you get this object.
        /// </summary>
        void ReleaseDisplay();
    }
    public class Display
    {
        private Display()
        {

        }

        private static readonly Lazy<Display> LazyInstance = new Lazy<Display>(() =>
        {
            return new Display();
        }, LazyThreadSafetyMode.ExecutionAndPublication);
        public static Display Instance => LazyInstance.Value;

        public delegate void MonitorStateHandler(bool on);
        public event MonitorStateHandler StateChanged;
        private bool ?_isOn;
        public bool IsOn 
        { 
            get 
            {
                return _isOn ?? true;
            }
            set
            {
                _isOn = value;
                StateChanged?.Invoke(value);
            }
        }

        /*
         * @return brightness  [0 ~ 1] or null
         */
        public double? GetBrightness()
        {
            try
            {
                return ServiceFactory.BrightnessService.Brightness / 100;
            }
            catch (Exception)
            {
                return null;
            }
        }

        /*
         * @param brightness  [0 ~ 1]
         */
        public void SetBrightness(double brightness)
        {
            if (brightness > 1) brightness = 1;
            if (brightness < 0) brightness = 0;
            ServiceFactory.BrightnessService.Brightness= (byte)(brightness * 100);
        }

        public Size GetCurrentSize()
        {
            var displayInformation = DisplayInformation.GetForCurrentView();
            TypeInfo t = typeof(DisplayInformation).GetTypeInfo();
            var props = t.DeclaredProperties.Where(x => x.Name.StartsWith("Screen") && x.Name.EndsWith("InRawPixels")).ToArray();
            var w = props.Where(x => x.Name.Contains("Width")).First().GetValue(displayInformation);
            var h = props.Where(x => x.Name.Contains("Height")).First().GetValue(displayInformation);
            var size = new Size(System.Convert.ToDouble(w), System.Convert.ToDouble(h));
            switch (displayInformation.CurrentOrientation)
            {
                case DisplayOrientations.Landscape:
                case DisplayOrientations.LandscapeFlipped:
                    size = new Size(Math.Max(size.Width, size.Height), Math.Min(size.Width, size.Height));
                    break;
                case DisplayOrientations.Portrait:
                case DisplayOrientations.PortraitFlipped:
                    size = new Size(Math.Min(size.Width, size.Height), Math.Max(size.Width, size.Height));
                    break;
            }
            return size;
        }

        public void Init()
        {
            ServiceFactory.NativeMessageService.MonitorStatusChanged += (b) =>
            {
                IsOn = b;
            };
        }

        /// <summary>
        /// you can just call this function on UI thread. 
        /// You must call this funtion after last object released.
        /// don't forget to release display.
        /// </summary>
        /// <returns>the object you can use to release display.</returns>
        public IDisplayReleaseHandler RequestDisplay()
        {
            Debug.WriteLine($"RequestDisplay");
            var displayRequest = new DisplayRequest();
            Debug.WriteLine($"displayRequest.RequestActive");
            displayRequest.RequestActive();
            DisplayReleaseHandler displayReleaseHandler = new DisplayReleaseHandler() { DisplayRequest=displayRequest};
            return displayReleaseHandler;
        }
        private class DisplayReleaseHandler : IDisplayReleaseHandler
        {
            public DisplayRequest DisplayRequest { get; set; }
            public void ReleaseDisplay()
            {
                Debug.WriteLine($"RleaseDisplay");
                if (DisplayRequest!=null)
                {
                    Debug.WriteLine($"displayRequest.Release success");
                    DisplayRequest.RequestRelease();
                    DisplayRequest = null;
                }
                else
                {
                    Debug.WriteLine($"already RleaseDisplay");
                }
            }
        }

    }
}
